package com.example.androidlib;

import com.example.androidlib.utils.Convert;
import com.example.androidlib.utils.FileUtil;
import com.example.androidlib.utils.NormalUtil;
import com.example.androidlib.wallet.TokenClient;
import com.example.androidlib.wallet.TransferToken;
import com.example.androidlib.wallet.WalletTools;
import com.example.androidlib.wallet.Web3jInfo;

import org.web3j.crypto.Bip39Wallet;
import org.web3j.crypto.CipherException;
import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.admin.Admin;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.core.methods.response.EthTransaction;
import org.web3j.protocol.core.methods.response.Transaction;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.utils.Numeric;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;


/**
 * @Description:
 * @author: zcs
 * @email: 1059737741@qq.com
 * create at 2022/3/2 12:37
 */
public class Test {
    //private static final Logger log = LoggerFactory.getLogger(Test.class);

    // 钱包存放路径
    String walletFilePathDir  = "F:\\android-demo\\nctest\\web3jextension\\src\\main\\java\\com\\huanyi\\web3jextension";
    // 钱包密码
    String password = "tianya123456qwe";

    private Web3j web3j;
    private Admin admin;
    private static Credentials credentials;
    String tempAddress;


    public static void main(String[] args)  throws Exception{
        Test test = new Test();

        //new Test().run1();

        test.connectETHClient();


        //test.createFullWallet(password);
        //test.createLightWallet(password);
        //test.createBip39Wallet(password);


        //String fullwalletFileName = "UTC--2022-03-04T01-58-57.579154200Z--49e57bf84a70db940fe6d4d9ca0f53e3b79a0264.json";
        //String lightwalletFileName = "UTC--2022-03-04T01-58-57.735429300Z--eec2b3a269a37648c3ea8e1df50cbdef4c13932d.json";

        //String lightwalletFileName = "UTC--2022-03-08T05-18-57.443820800Z--62c2e4d94fc0f8ada5ef44399f93c9b5b3d1c388.json";
        //String mnemonic = "submit elder horn remain bid relax foster rate another thunder accident desert";
        //String mnemonic = "junior lizard bomb alien tank slim few reduce spy silver talk fancy"; //本地 无json，不可行

        //test.loadWallet(password,fullwalletFileName);
        //test.loadWallet(test.password,lightwalletFileName);

        //String prikey = "4d8b859a4def37a6731b22ccd4345feb78bebb7054a9e6c2649b2a72c4fa217a";//true  本地有文件
        //String prikey = "35074603175219071994932854545596796916526259183916651607639933418511319835002"; //
        String prikey = "3b8020d16ba2021ec7ff880a3323c40893dfd2146c4dfbb139ed8d5174b4bcc3"; // 本地无文件
        //String prikey = "4d8b859a4def37a6731b22ccd4345feb78bebb7054a9e6c2649b2a72c4fa217a"; //
        //test.loadWallet(test.password,lightwalletFileName);
        //test.loadWalletByMnemonic(test.password, mnemonic);//密码不需要
        //私钥
        test.loadWalletByPrivateKey(prikey);

        //test.getBlanceOf(credentials.getAddress());

        String address_to = "0x49e57bF84a70DB940Fe6d4d9Ca0F53e3B79a0264";
        //test.transto(address_to,BigDecimal.valueOf(0.2));

        //EthSendTransaction ethSendTransaction = test.transtoCustom(address_to,BigInteger.valueOf(1));
        String hash = "0x7a6181a4ad8c7eff9bb27723893c949c49ed56c16a29ae024088c8df0d7f635f";
        test.getTransactionByHash(hash);

        //test.getBlanceOf(credentials.getAddress());
        //test.getNonce(credentials.getAddress());



        //test.crareAndRead(password);
        //BigInteger bigInteger = NormalUtil.requestCurrentGasPrice(test.web3j);
        //System.out.println("CurrentGasPrice="+ bigInteger);//1024


       // test.transferERC20();
        //代币
        test.contractBalanceOf();



    }

    private void connectETHClient() throws IOException {
        web3j = Web3jInfo.connect();
        admin = Web3jInfo.connectAdmin();
        //测试是否连接成功  获取版本号
        String web3ClientVersion = web3j.web3ClientVersion().send().getWeb3ClientVersion();
        System.out.println("version="+web3ClientVersion);

        String account_string = "";
        List<String> accounts = web3j.ethAccounts().send().getResult();
        account_string += accounts.size();
        for (String account:accounts){
            account_string += "  \n " + account;
        }
        System.out.println("account_string="+account_string);

    }

    //不使用
    private void createFullWallet(String password) throws InvalidAlgorithmParameterException, CipherException, NoSuchAlgorithmException, IOException, NoSuchProviderException {
        //创建完整类型的钱包
        //var walletFileName0 = WalletUtils.generateNewWalletFile(password, File(walletFilePathDir, ""), false) //根据密码生成钱包到地址路径
        String walletFileName = WalletTools.createWalletFull(password,walletFilePathDir);
        System.out.println("fullwalletFileName: " + walletFileName);
    }
    //
    private void createLightWallet(String password) throws InvalidAlgorithmParameterException, CipherException, NoSuchAlgorithmException, IOException, NoSuchProviderException {
        //创建一个简单钱包
        String walletFileName = WalletTools.createWalletLight(password,walletFilePathDir);//根据密码生成钱包到地址路径
        System.out.println("lightwalletFileName: " + walletFileName);
        //return walletFileName
    }
    private void createBip39Wallet(String password) throws CipherException, IOException {
        String walletFileDestDir = walletFilePathDir + "/123" ;

        FileUtil.createOrExistsDir(new File(walletFilePathDir));
        Bip39Wallet bip39Wallet = WalletUtils.generateBip39Wallet(password,new File(walletFilePathDir));//助记词钱包生成
        //LogUtil.e("助记词 ${bip39Wallet.mnemonic}")
        System.out.println("助记词:"+ bip39Wallet.getMnemonic());
        System.out.println("助记词json:"+ bip39Wallet.getFilename());
        Boolean result = FileUtil.writeFileFromLineString(new File(walletFileDestDir), bip39Wallet.getMnemonic(), true);

        //Boolean result = WalletTools.createWallet(password,walletFilePathDir,walletFileDestDir);
        //val bip39Wallet: Bip39Wallet = WalletUtils.generateBip39Wallet("",File(walletFilePathDir))//助记词钱包生成
        //LogUtil.e("助记词 ${result}")
        System.out.println("result:"+ result);
    }

//    private void crareAndRead(String password) throws InvalidAlgorithmParameterException, CipherException, IOException, NoSuchAlgorithmException, NoSuchProviderException {
//        //生成钱包，对应目录下会创建对应的私钥文件。
//        String walletFileName = WalletUtils.generateNewWalletFile(password, new File(walletFilePathDir), false);
//        // 加载指定位置的钱包
//        Credentials credentials = WalletUtils.loadCredentials(password, walletFilePathDir + "/" + walletFileName);
//
//
//        String address = credentials.getAddress();
//        System.out.println("address:" + address);
//        System.out.println("PrivateKey:" + credentials.getEcKeyPair().getPrivateKey());
//        System.out.println("PublicKey:" + credentials.getEcKeyPair().getPublicKey());
//
//    }




    private void loadWallet(String password,String walletFileName) throws CipherException, IOException {
        String walletFilePath = walletFilePathDir + "/"+ walletFileName;

        //val credentials = WalletUtils.loadCredentials(password, walletFilePath)
        credentials = WalletTools.loadWallet(password, walletFilePath);
        tempAddress = credentials.getAddress();
        System.out.println("address length :"+ tempAddress.length());
        System.out.println("PrivateKey length :"+ credentials.getEcKeyPair().getPrivateKey().toString().length());
        System.out.println("PublicKey length :"+ credentials.getEcKeyPair().getPublicKey().toString().length());
        System.out.println("PrivateKey:"+ credentials.getEcKeyPair().getPrivateKey());
        System.out.println("--------------------:");
        System.out.println(("privateKey："+Numeric.encodeQuantity(credentials.getEcKeyPair().getPrivateKey())));
        System.out.println(("PublicKey："+Numeric.encodeQuantity(credentials.getEcKeyPair().getPublicKey())));
        //LogUtil.e("credentials", credentials)
        //return GsonUtil.objToJsonString(credentials)
    }

    // 2根据私钥 加载钱包,
    // 返回新的json,不使用
    private void loadWalletByPrivateKey(String inputPrivateKey) {
        //LogUtil.e("privateKey: ${inputPrivateKey}")
        credentials = WalletTools.loadWalletByPrivateKey(inputPrivateKey);
        System.out.println("--------------------:");
        System.out.println(("privateKey："+Numeric.encodeQuantity(credentials.getEcKeyPair().getPrivateKey())));
        System.out.println(("PublicKey："+Numeric.encodeQuantity(credentials.getEcKeyPair().getPublicKey())));
        tempAddress = credentials.getAddress();
        //return GsonUtil.objToJsonString(credentials)
    }
    // 3根据助记词加载钱包
    private void  loadWalletByMnemonic(String password,String mnemonic){
        credentials =  WalletTools.loadWalletByMnemonic(password, mnemonic);
        tempAddress = credentials.getAddress();
        System.out.println("--------------------:");
        System.out.println(("privateKey："+Numeric.encodeQuantity(credentials.getEcKeyPair().getPrivateKey())));
        System.out.println(("PublicKey："+Numeric.encodeQuantity(credentials.getEcKeyPair().getPublicKey())));
        //LogUtil.e("credentials", credentials)
        //return GsonUtil.objToJsonString(credentials)
    }

    //
    private void  getBlanceOf(String address) throws IOException {
        web3j = Web3jInfo.connect();
        BigInteger blance = NormalUtil.getBalanceOf(web3j,address);
        String blanceETH = NormalUtil.getBalanceOfString(web3j,address);

        System.out.println("余额："+blance);//17899886790000000000
        System.out.println("余额 转eth："+blanceETH);//17.89988679
        //LogUtil.e("余额："+blanceETH)
        //return blanceETH
    }

    //
    private void  getNonce(String address) throws ExecutionException, InterruptedException {
        web3j = Web3jInfo.connect();
        BigInteger nonce = NormalUtil.getNonce(web3j, address);
        System.out.println("交易笔数："+nonce);//3
        //return blanceETH
    }


    //发送以太币
    private TransactionReceipt transto(String address_to,BigDecimal amount) throws Exception {
        TransactionReceipt transactionReceipt = TransferToken.transfer(web3j,credentials,address_to,amount);
        //TransferToken.transferAsync(web3j,credentials,address_to,amount);
        return transactionReceipt;
    }
    private EthSendTransaction transtoCustom(String address_to,BigInteger amount) throws Exception {
        //TransferToken.transfer(web3j,credentials,address_to,amount);
        //TransferToken.transferAsync(web3j,credentials,address_to,amount);
        //自定义交易


        BigInteger value = com.example.androidlib.utils.Convert.toWei(1+"", com.example.androidlib.utils.Convert.Unit.ETHER);
        BigInteger gasPrice = com.example.androidlib.utils.Convert.toWei(40+"", com.example.androidlib.utils.Convert.Unit.GWEI);
        BigInteger gasLimit = BigInteger.valueOf(21000);

        EthSendTransaction ethSendTransaction = TransferToken.transferCustom(web3j,credentials,gasPrice, gasLimit, address_to, value);
        return ethSendTransaction;
    }
    //
    private void transferERC20() throws IOException, ExecutionException, InterruptedException {
        BigInteger value = Convert.toWei("100", Convert.Unit.ETHER);
        TransferToken.transferERC20(web3j,credentials,credentials.getAddress(),"0x8C16c96E8715aD9F890AB300E9895f7E4Da3614a",value,"0x5e06f21c8b16Ba42E143F814E551380B38594898");
    }


    private void getTransactionByHash(String hash) throws IOException {
        EthTransaction ethTransaction = TransferToken.getTransactionByHash(web3j, hash);
        Optional<Transaction> transaction = ethTransaction.getTransaction();

        System.out.println("查询交易详情 :" + transaction);
    }

    private void contractBalanceOf(){
        Web3j web3j = Web3jInfo.connect();

        BigInteger balance = TokenClient.getAddressBalanceOf(web3j, "0x5e06f21c8b16Ba42E143F814E551380B38594898", "0x46Bf521e93e3fE4e3413CC586187b9b85FFAFd3a");
        System.out.println("当前地址ENS的余额:" + balance);
        System.out.println("当前地址ENS的余额:" + Convert.fromWei(balance,Convert.Unit.ETHER));
        BigInteger total = TokenClient.getTokenTotalSupply(web3j, "0x5e06f21c8b16Ba42E143F814E551380B38594898");
        System.out.println("loot（0x5e06f21c8b16Ba42E143F814E551380B38594898） total:" + total);

    }



    private void run1() throws Exception {
        System.out.println("hello eth,hello web3j");

        Web3j web3j = Web3jInfo.connect();

        BigInteger balance = TokenClient.getAddressBalanceOf(web3j, "0x5e06f21c8b16Ba42E143F814E551380B38594898", "0x0fb6160F1738ee5243cB3ED421dc0CEa2cf1C0D4");
        System.out.println("当前地址ENS的余额:" + balance);
        BigInteger total = TokenClient.getTokenTotalSupply(web3j, "0x5e06f21c8b16Ba42E143F814E551380B38594898");
        //BigInteger total = TokenClient.getTokenTotalSupply(web3j, "0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7");
        System.out.println("loot（0x5e06f21c8b16Ba42E143F814E551380B38594898） total:" + total);

//        TransMonitor.getInstance().setWeb3j(web3j);
//        TransMonitor.getInstance().subscribeContract("0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", new Action1<Log>() {
//            @Override
//            public void call(Log log) {
//                System.out.println("transBlockNo:" + log.getBlockNumber());
//                System.out.println("transHash:" + log.getTransactionHash());
//                List<String> topics = log.getTopics();
//                for (String topic : topics) {
//                    System.out.println("transTopic:" + topic);
//                }
//            }
//        });
//        NFTMonitor.getInstance().setWeb3j(web3j);

        /***
         * Loot的合约
         *
         * ***/
//        NFTMonitor.getInstance().subscribeClaim("0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7", new Action1<Log>() {
//            @Override
//            public void call(Log log) {
//                /**
//                 * 这些tokeniD已经被抢走了，抢还没有claim的
//                 *
//                 * **/
//                System.out.println("transBlockNo:" + log.getBlockNumber());
//                System.out.println("transHash:" + log.getTransactionHash());
//
//            }
//        });


        //轮巡器，或者job定时任务，抢NFT
//        new Timer().schedule(new TimerTask() {
//            @Override
//            public void run() {
//                //根据当前已出现的ID，找出还没出现在的,还未实现只是例子
//                TokenClient.claimNFT(web3j, "0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7", 9527);
//            }
//        }, 0L, 1000L);//每秒执行抢NFT逻辑

//        TransMonitor.getInstance().setWeb3j(web3j);
//        TransMonitor.getInstance().subscribeBlock(new Action1<EthBlock>() {
//            @Override
//            public void call(EthBlock ethBlock) {
//                System.out.println("block:" + ethBlock.getBlock().getHash() + ",author" + ethBlock.getBlock().getAuthor());
//            }
//        });
//
//        TransMonitor.getInstance().subscribeHasTrans(new Action1<Transaction>() {
//            @Override
//            public void call(Transaction transaction) {
//                System.out.println("from:" + transaction.getFrom() + ",to" + transaction.getTo());
//            }
//        });
//
//        TransMonitor.getInstance().subscribePendingTrans(new Action1<Transaction>() {
//            @Override
//            public void call(Transaction transaction) {
//                System.out.println("pending from:" + transaction.getFrom() + ",to" + transaction.getTo()+",gasPrice"+transaction.getGasPrice());
//            }
//        });


//       BigInteger total = TokenClient.getTokenTotalSupply(Web3jInfo.connect(),"0xff9c1b15b16263c61d017ee9f65c50e4ae0113d7");
//        System.out.println("loot total:"+total);
//        Subscription sub = Web3jInfo.connect().transactionObservable().subscribe(tx -> {
//            System.out.println("hash: " + tx.getHash());
//            System.out.println("from: " + tx.getFrom());
//            System.out.println("to: " + tx.getTo());
//            System.out.println("value:"+tx.getValue());
//        });



//        WalletTools.createWallet("d:\\keystore\\abs","d:\\keystore\\abs\\123");
//        connectETHClient();//连接以太坊客户端
//        creatAccount();//创建冷钱包
//        String privateKey = "";
        String keyStoreDir = WalletUtils.getDefaultKeyDirectory();
        System.out.println("生成keyStore文件的默认目录：" + keyStoreDir);
        //通过密码及keystore目录生成钱包
        //Bip39Wallet wallet = WalletUtils.generateBip39Wallet("123456", new File(keyStoreDir));
        //keyStore文件名
//        System.out.println(wallet.getFilename());
//        //12个单词的助记词
//        System.out.println(wallet.getMnemonic());

//        Scanner scanner = new Scanner(System.in);
//        privateKey = scanner.next();
//        //
//        loadWalletByPrivateKey(privateKey);//加载钱包
//        //先获取Sign码

        //getBlanceOf();//查询账户余额
        //transto();//转账到指定地址
    }
}
